// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin_JXGM ql1746365080@gmail.com
 * @Date: 2024-10-22 16:01:12
 * @LastEditors: qiulin_JXGM ql1746365080@gmail.com
 * @LastEditTime: 2024-12-19 16:18:38
 * @FilePath: \SGFEM\Import\BDFImport\BulkData\Load\PLOAD4Parser.cpp
 */

#include "Import/BDFImport/BulkData/Load/PLOAD4Parser.h"

#include <algorithm>
#include <cstdint>

#include <boost/algorithm/string.hpp>

#include "Utility/Logging/SGLogger.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Load/IPLOAD4Service.h"

#include "Import/BDFImport/BDFParserBase.h"
BULKDATA_ENTRY_PARSER_REG (PLOAD4);

using namespace SG::DBManager;
using namespace SG::Import;
using namespace SG::DataStructure;
/*
// file://./../../Doc/MarkDown/BulkData/PLOAD4/PLOAD4.md>
*/
// 以下需要修改
enum PLOAD4Key : uint8_t
{
    PLOAD4_SID   = 2,   // Load set identification number. (Integer > 0)
    PLOAD4_EID   = 3,   // Element identification number. (Integer > 0)
    PLOAD4_P1    = 4,   // Load per unit surface area at corner 1. (Real)
    PLOAD4_P2    = 5,   // Load per unit surface area at corner 2. (Real)
    PLOAD4_P3    = 6,   // Load per unit surface area at corner 3. (Real)
    PLOAD4_P4    = 7,   // Load per unit surface area at corner 4. (Real)
    PLOAD4_G1    = 8,   // Grid point G1. (Integer > 0)
    PLOAD4_G3_G4 = 9,   // Grid point G3 or G4 depending on element type. (Integer > 0)
    PLOAD4_CID   = 12,  // Coordinate system identification number. (Integer ≥ 0; Default = 0)
    PLOAD4_N1    = 13,  // Vector component N1 in CID coordinate system. (Real)
    PLOAD4_N2    = 14,  // Vector component N2 in CID coordinate system. (Real)
    PLOAD4_N3    = 15,  // Vector component N3 in CID coordinate system. (Real)
    PLOAD4_SORL  = 16,  // Surface or line load indicator (SURF or LINE). (Character)
    PLOAD4_LDIR  = 17   // Load direction for line loads. (Character)
};
SG::DataStructure::Common::Status BDF::BULKDATA::ParsePLOAD4 (const std::shared_ptr<SG::DBManager::DBServiceFactory>& dbServiceFactory,
                                                              std::vector<std::string>&                               dividedEntryInfo)
{
    SG::DataStructure::FEM::PLOAD4Data tempdata;
    std::strncpy (tempdata.m_sorl, "SURF", 5);
    std::strncpy (tempdata.m_ldir, "NORM", 5);
    // TODO(bug 001) m_dominId的正确填写，当前默认domainId设置为1
    tempdata.m_domainId = 1;

    // 当前词条的索引，初始值为1
    int                            curIDKey          = 1;
    bool                           p234isEmpty       = true;   // 默认p2 p3 p4均为空
    bool                           isAlternateFormat = false;  // 是否为第二种格式
    SG::DataStructure::Common::I64 eid2              = 0;      // 记录第二种格式
    // 遍历分割后的词条信息
    for (auto curStrKey : dividedEntryInfo)
    {
        // 检查当前词条是否为空白
        bool const isEmpty = is_all_space (curStrKey);
        if (isEmpty)
        {
            curIDKey++;
            continue;  // 如果是空白，跳过当前词条
        }

        // 将词条转换为科学计数法格式

        // 根据当前词条索引，匹配对应的PLOAD4属性

        switch (curIDKey)
        {
        case PLOAD4_SID:
            // Handle Load set identification number (SID)
            tempdata.m_sId = convertToI64 (curStrKey);
            break;
        case PLOAD4_EID:
            // Handle Element identification number (EID)
            tempdata.m_eId = convertToI64 (curStrKey);
            break;
        case PLOAD4_P1:
            // Handle Load per unit surface area at corner 1 (P1)
            tempdata.m_P[0] = convertToReal (curStrKey);
            break;
        case PLOAD4_P2:
            // Handle Load per unit surface area at corner 2 (P2)
            tempdata.m_P[1] = convertToReal (curStrKey);
            p234isEmpty     = false;
            break;
        case PLOAD4_P3:
            // Handle Load per unit surface area at corner 3 (P3)
            if (false == p234isEmpty)
            {
                SGError << "ParsePLOAD4, P2 is null, but P3 has value ";
            }
            tempdata.m_P[2] = convertToReal (curStrKey);
            break;
        case PLOAD4_P4:
            // Handle Load per unit surface area at corner 4 (P4)
            if (false == p234isEmpty)
            {
                SGError << "ParsePLOAD4, P2 is null, but P4 has value ";
            }
            tempdata.m_P[3] = convertToReal (curStrKey);
            // p234isEmpty     = false;
            break;
        case PLOAD4_G1:
            // Handle Grid point G1
            if (boost::icontains (curStrKey, "THRU"))
            {
                isAlternateFormat = true;
            }
            else
            {
                tempdata.m_G1 = convertToI64 (curStrKey);
            }

            break;
        case PLOAD4_G3_G4:
            // Handle Grid point G3 or G4
            if (isAlternateFormat)
            {
                eid2 = convertToI64 (curStrKey);
            }
            else
            {
                tempdata.m_G34 = convertToI64 (curStrKey);
            }
            break;
        case PLOAD4_CID:
            // Handle Coordinate system identification number (CID)
            tempdata.m_cId = convertToI64 (curStrKey);
            break;
        case PLOAD4_N1:
            // Handle Vector component N1 in CID coordinate system
            tempdata.m_N[0] = convertToReal (curStrKey);
            break;
        case PLOAD4_N2:
            // Handle Vector component N2 in CID coordinate system
            tempdata.m_N[1] = convertToReal (curStrKey);
            break;
        case PLOAD4_N3:
            // Handle Vector component N3 in CID coordinate system
            tempdata.m_N[2] = convertToReal (curStrKey);
            break;
        case PLOAD4_SORL:
            // Handle Surface or line load indicator (SURF or LINE)
            boost::trim (curStrKey);  // 去除字符串两边的空格
            // 将GROUP字符串复制到tempData的m_group字段中
            std::strncpy (
                tempdata.m_sorl, boost::algorithm::trim_copy (curStrKey).c_str (), boost::algorithm::trim_copy (curStrKey).size ());
            break;
        case PLOAD4_LDIR:
            // Handle Load direction for line loads
            boost::trim (curStrKey);  // 去除字符串两边的空格
            // 将GROUP字符串复制到tempData的m_group字段中
            std::strncpy (
                tempdata.m_ldir, boost::algorithm::trim_copy (curStrKey).c_str (), boost::algorithm::trim_copy (curStrKey).size ());
            break;
        default:
            // Handle unknown key
            break;
        }

        // 处理完当前词条后，索引递增
        curIDKey++;
    }

    if (p234isEmpty)
    {
        tempdata.m_P[3] = tempdata.m_P[2] = tempdata.m_P[1] = tempdata.m_P[0];
    }

    // 第二种格式, 载荷作用到一系列单元上
    if (isAlternateFormat)
    {
        for (SG::DataStructure::Common::I64 eid = tempdata.m_eId - 1; eid < eid2; eid++)
        {
            tempdata.m_eId = eid + 1;
            if (dbServiceFactory->get<IPLOAD4Service> ()->Add (tempdata) == SG::DataStructure::Common::Status::STATUS_Failure)
            {
                return SG::DataStructure::Common::Status::STATUS_Failure;
            }
        }
        return SG::DataStructure::Common::Status::STATUS_Success;
    }

    return dbServiceFactory->get<IPLOAD4Service> ()->Add (tempdata);
}